import { ResolvedOptions } from '../options'
import { hashString } from '../utils'
import { globalInjectModules } from './modules/_utils'

const virtualModulesSymbol = Symbol()
export const getVirtualModules = (options: ResolvedOptions): Record<string, string> => {
  return (
    (options as any)[virtualModulesSymbol] ??
    ((options as any)[virtualModulesSymbol] = Object.create(globalInjectModules))
  )
}

function registerVirtualModule(this: Record<string, string>, code: string) {
  let i = 0
  let rawId = 'wasm-virtual:' + hashString(code as any)
  let id: string
  while ((id = rawId + i++) in this && this[id] !== code);
  this[id] = code
  return id
}

export const defineHelper = <T>(
  createHelper: (options: ResolvedOptions, registerVirtualModule: (code: string) => string) => T
): ((options: ResolvedOptions) => T) => {
  const symbol = Symbol()

  return (options: any) => {
    if (options[symbol]) {
      return options[symbol]
    }
    const virtualModules = getVirtualModules(options)
    return (options[symbol] = createHelper(options, registerVirtualModule.bind(virtualModules)))
  }
}
